package com.winit.openapi.erp.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.winit.common.email.MailContentService;
import com.winit.common.spi.SPIException;
import com.winit.common.spi.context.CommandContext;
import com.winit.common.spring.SpringMessageLocator;
import com.winit.erp.spi.bpartner.BpartnerService;
import com.winit.erp.spi.bpartner.command.BpartnerCommand;
import com.winit.erp.spi.bpartner.vo.Bpartner;
import com.winit.erp.spi.product.ProductService;
import com.winit.erp.spi.product.vo.Product;
import com.winit.erp.spi.shareorder.ShareOrderService;
import com.winit.erp.spi.shareorder.command.QueryShareOrderCommand;
import com.winit.erp.spi.shareorder.vo.ShareOrder;
import com.winit.erp.spi.storage.WarehouseStorageService;
import com.winit.erp.spi.storage.command.WarehouseStorageCommand;
import com.winit.erp.spi.storage.vo.WarehouseStorage;
import com.winit.erp.spi.user.UserService;
import com.winit.erp.spi.user.command.UserCommand;
import com.winit.erp.spi.user.vo.User;
import com.winit.ims.spi.share.ShareOrderLineSellService;
import com.winit.ims.spi.share.command.CreateShareOrderLineSellCommand;
import com.winit.ims.spi.share.command.UpdateShareOrderLineSellCommand;
import com.winit.ims.spi.share.vo.ShareOrderLineSell;
import com.winit.oms.spi.ParamsValidateException;
import com.winit.oms.spi.share.ShareOrderSellService;
import com.winit.oms.spi.share.command.CreateShareOrderSellCommand;
import com.winit.oms.spi.share.command.InvalidShareOrderSellCommand;
import com.winit.oms.spi.share.vo.ShareOrderSell;
import com.winit.openapi.constants.EnumConstant;
import com.winit.openapi.constants.ErrorCode;
import com.winit.openapi.controller.BaseController;
import com.winit.openapi.exception.ApiException;
import com.winit.openapi.model.RequestMsg;
import com.winit.openapi.model.ResponseMsg;
import com.winit.openapi.util.ValidateUtil;
import com.winit.push.spi.EmailService;
import com.winit.push.spi.command.SendEmailCommand;
import com.winit.ums.spi.UmsCustomerService;
import com.winit.ums.spi.commnad.CustomerQueryCommand;
import com.winit.ums.spi.vo.CustomerInfoVO;

/**
 * 库存共享单服务
 * 
 * @author long.chen 2015-4-17 下午2:05:33
 * @since 1.0
 */
@Controller
@RequestMapping(value = "/shareOrder")
public class ShareOrderController extends BaseController {

    private Logger                    logger      = LoggerFactory.getLogger(ShareOrderController.class);
    private static final String       OPER_ADD    = "Add";
    private static final String       OPER_MODIFY = "Modify";

    @Resource
    private ShareOrderSellService     shareOrderSellService;
    @Resource
    private ShareOrderLineSellService shareOrderLineSellService;
    @Resource
    private WarehouseStorageService   warehouseStorageService;
    @Resource
    private ProductService            erpProductService;
    @Resource
    private ShareOrderService         shareOrderService;
    @Resource
    BpartnerService                   bpartnerService;
    @Resource
    UserService                       userService;
    @Resource
    EmailService                      emailService;
    @Resource
    UmsCustomerService                umsCustomerService;
    @Resource
    private MailContentService        freemarkerMailContentService;
    // 配置文件中的客服邮箱
    @Value(value = "${cs.email}")
    private String                    csEmail;

    /**
     * 创建库存共享单
     * 
     * @param requestMsg
     * @param responseMsg
     * @return String
     */
    @RequestMapping(value = "/createShareOrder")
    public String createShareOrder(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        try {
            // 解析参数
            JSONObject json = (JSONObject) requestMsg.getData();
            // 创建共享单
            ShareOrderSell order = createShareOrder(json, EnumConstant.ShareOrderStatus.DR.getVal());
            // 返回共享单ID
            Map<String, String> data = new HashMap<String, String>();
            data.put("shareOrderId", String.valueOf(order.getShareOrderId()));
            responseMsg.setData(data);
            return SUCCESS;
        } catch (ApiException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (ParamsValidateException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (SPIException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (Exception e) {
            responseMsg.setCode(ErrorCode.SHAREORDER_CREATE_ERROR);
            String msg = SpringMessageLocator.getMessage(ErrorCode.SHAREORDER_CREATE_ERROR, CommandContext.getContext()
                .getLocale());
            responseMsg.setMsg(msg);
            logger.error("创建库存共享单异常！", e);
        }
        return ERROR;
    }

    /**
     * 保存共享产品明细
     * 
     * @param requestMsg
     * @param responseMsg
     * @return String
     */
    @RequestMapping(value = "/saveShareOrderLine")
    public String saveShareOrderLine(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {

        try {
            // 解析参数
            JSONObject json = (JSONObject) requestMsg.getData();
            ValidateUtil.valid(json, "shareOrderId", 10, true);

            // 共享单ID
            Long shareOrderId = json.getLongValue("shareOrderId");

            CreateShareOrderLineSellCommand command = new CreateShareOrderLineSellCommand();
            command.setShareOrderId(shareOrderId);

            // 查询共享单
            QueryShareOrderCommand query = new QueryShareOrderCommand();
            query.setShareOrderId(shareOrderId);
            List<ShareOrder> listShareOrder = shareOrderService.queryShareOrder(query);
            if (listShareOrder == null || listShareOrder.isEmpty()) {
                String msg = SpringMessageLocator.getMessage(ErrorCode.FIELD_SHARE_ORDER_NOT_EXIST,
                    CommandContext.getContext().getLocale());
                responseMsg.setCode(ErrorCode.FIELD_SHARE_ORDER_NOT_EXIST);
                responseMsg.setMsg(msg);
                logger.warn("共享单(" + shareOrderId + ")不存在");
                return ERROR;
            }

            // 共享产品明细列表
            List<ShareOrderLineSell> productList = getProductList(json, listShareOrder.get(0), OPER_ADD);
            command.setProductList(productList);
            command.setShareType(json.getString("shareType"));
            // 调用接口创建共享单产品明细
            shareOrderLineSellService.addShareOrderLine(command);
            return SUCCESS;
        } catch (ApiException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (ParamsValidateException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (SPIException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (Exception e) {
            responseMsg.setCode(ErrorCode.SHAREORDER_SAVE_DETAIL_ERROR);
            String msg = SpringMessageLocator.getMessage(ErrorCode.SHAREORDER_SAVE_DETAIL_ERROR,
                CommandContext.getContext().getLocale());
            responseMsg.setMsg(msg);
            logger.error("保存共享产品明细异常！", e);
        }
        return ERROR;

    }

    /**
     * 编辑共享产品明细
     * 
     * @param requestMsg
     * @param responseMsg
     * @return String
     */
    @RequestMapping(value = "/modifyShareOrderLine")
    public String modifyShareOrderLine(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        try {
            // 解析参数
            JSONObject json = (JSONObject) requestMsg.getData();
            ValidateUtil.valid(json, "shareOrderId", 10, true);
            ValidateUtil.valid(json, "effectiveDate", 0, false);
            ValidateUtil.valid(json, "expiredDate", 0, false);

            // 共享单ID
            Long shareOrderId = json.getLongValue("shareOrderId");
            UpdateShareOrderLineSellCommand command = new UpdateShareOrderLineSellCommand();
            command.setShareOrderId(shareOrderId);
            command.setEffectiveDate(json.getDate("effectiveDate"));
            command.setExpiredDate(json.getDate("expiredDate"));

            // 查询共享单
            QueryShareOrderCommand query = new QueryShareOrderCommand();
            query.setShareOrderId(shareOrderId);
            List<ShareOrder> listShareOrder = shareOrderService.queryShareOrder(query);
            if (listShareOrder == null || listShareOrder.isEmpty()) {
                String msg = SpringMessageLocator.getMessage(ErrorCode.FIELD_SHARE_ORDER_NOT_EXIST,
                    CommandContext.getContext().getLocale());
                responseMsg.setCode(ErrorCode.FIELD_SHARE_ORDER_NOT_EXIST);
                responseMsg.setMsg(msg);
                logger.warn("共享单(" + shareOrderId + ")不存在");
                return ERROR;
            }

            // 共享产品明细列表
            List<ShareOrderLineSell> productList = getProductList(json, listShareOrder.get(0), OPER_MODIFY);
            command.setProductList(productList);
            command.setShareType(json.getString("shareType"));
            // 编辑共享产品明细
            shareOrderLineSellService.updateShareOrderLine(command);
            return SUCCESS;
        } catch (ApiException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (ParamsValidateException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (SPIException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (Exception e) {
            responseMsg.setCode(ErrorCode.SHAREORDER_UPDATE_DETAIL_ERROR);
            String msg = SpringMessageLocator.getMessage(ErrorCode.SHAREORDER_UPDATE_DETAIL_ERROR,
                CommandContext.getContext().getLocale());
            responseMsg.setMsg(msg);
            logger.error("编辑共享产品明细失败！", e);
        }

        return ERROR;
    }

    /**
     * 取消合作
     * 
     * @param requestMsg
     * @param responseMsg
     * @return String
     */
    @RequestMapping(value = "/cancleShareOrder")
    public String cancleShareOrder(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        try {
            // 解析参数
            JSONObject json = (JSONObject) requestMsg.getData();
            ValidateUtil.valid(json, "shareOrderId", 10, true);

            // 共享单ID
            Long shareOrderId = json.getLongValue("shareOrderId");
            InvalidShareOrderSellCommand command = new InvalidShareOrderSellCommand();
            command.setShareOrderId(shareOrderId);
            // 取消作废共享单
            shareOrderSellService.invalidShareOrder(command);
            return SUCCESS;
        } catch (ApiException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (ParamsValidateException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (SPIException e) {
            responseMsg.setCode(e.getErrorCode());
            responseMsg.setMsg(e.getErrorMsg());
            logger.error(e.getErrorMsg(), e);
        } catch (Exception e) {
            responseMsg.setCode(ErrorCode.SHAREORDER_CANCLE_ERROR);
            String msg = SpringMessageLocator.getMessage(ErrorCode.SHAREORDER_CANCLE_ERROR, CommandContext.getContext()
                .getLocale());
            responseMsg.setMsg(msg);
            logger.error("取消合作异常", e);
        }
        return ERROR;
    }

    /**
     * 获取产品列表
     * 
     * @param json 参数对象
     * @param order 共享单
     * @param oper 业务操作（Add:增加 Modify：编辑）
     * @return List<ShareOrderLineSell>
     */
    private List<ShareOrderLineSell> getProductList(JSONObject json, ShareOrder order, String oper) {
        List<ShareOrderLineSell> list = new ArrayList<ShareOrderLineSell>();
        ValidateUtil.valid(json, "C_BPartner_ID", 10, true);
        ValidateUtil.valid(json, "M_Warehouse_ID", 10, true);
        // 共享方ID
        Long C_BPartner_ID = json.getLongValue("C_BPartner_ID");
        // 仓库ID
        Long warehouseId = json.getLongValue("M_Warehouse_ID");

        JSONArray jsonArr = json.getJSONArray("productList");
        for (int i = 0; i < jsonArr.size(); i++) {
            JSONObject jsonObj = (JSONObject) jsonArr.get(i);

            ValidateUtil.valid(jsonObj, "M_Product_ID", 10, true);
            ValidateUtil.valid(jsonObj, "qty", 10, true);

            // 产品ID
            Long productId = jsonObj.getLongValue("M_Product_ID");
            // 产品数量
            BigDecimal qty = new BigDecimal(jsonObj.getString("qty"));
            // 库存为0
            if (BigDecimal.ZERO.compareTo(qty) == 1) {
                // 产品数量小于1
                throw new ApiException(ErrorCode.FIELD_ERROR, "qty");
            }

            Product product = erpProductService.getProductId(productId);
            if (product == null || product.getProductId() == 0) {
                // 产品不存在
                throw new ApiException(ErrorCode.FIELD_SHARE_PRODUCT_NOT_EXIST, "M_Product_ID");
            }
            if (C_BPartner_ID.compareTo(product.getcBpartnerId()) != 0) {
                // 共享产品不属于共享方，用户不能访问产品
                throw new ApiException(ErrorCode.FIELD_PRODUCT_NOT_SHARE, "C_BPartner_ID");
            }

            WarehouseStorageCommand command = new WarehouseStorageCommand();
            command.setProductID(productId);
            command.setWarehouseID(warehouseId);
            // 查询库存数据
            WarehouseStorage storage = warehouseStorageService.queryStorage(command);
            if (storage != null) {
                // 可用库存 = 在库库存 - 保留库存 - 共享库存
                BigDecimal qtyAvailable = BigDecimal.ZERO;
                // 编辑共享产品明细，需要先将之前共享出去的库存还原回来，再重新分配新的共享库存
                if (OPER_MODIFY.equals(oper)) {
                    qtyAvailable = storage.getQtyonhand().subtract(storage.getQtyreserved());
                } else {
                    // 新增时,可用库存需要减去共享库存
                    qtyAvailable = storage.getQtyonhand()
                        .subtract(storage.getQtyreserved())
                        .subtract(storage.getQtysharestorage());
                }

                if (qty.compareTo(qtyAvailable) == 1) {
                    // 库存不够
                    throw new ApiException(ErrorCode.FIELD_QTYAVAILABLE_NOT_ENOUGH, "qtyAvailable");
                }
            } else {
                // 库存不够
                throw new ApiException(ErrorCode.FIELD_QTYAVAILABLE_NOT_ENOUGH, "qtyAvailable");
            }

            ShareOrderLineSell line = new ShareOrderLineSell();
            line.setShareOrderId(order.getShareOrderId());
            line.setFromBpartnerId(order.getBpartnerId());// 业务伙伴(共享方)
            line.setToBpartnerId(order.getShareBpartnerId());
            line.setProductId(productId);// 产品ID
            line.setSku(product.getSku());// SKU
            line.setProductValue(product.getValue());// 产品编码
            line.setWarehouseId(warehouseId);
            line.setShareProductNum(qty);// 产品数量
            list.add(line);
        }
        return list;
    }

    /**
     * 创建共享单
     * 
     * @param json
     * @param status
     * @return ShareOrderSell
     */
    private ShareOrderSell createShareOrder(JSONObject json, String status) {
        // 参数校验
        ValidateUtil.valid(json, "fromBpartnerId", 15, true);
        ValidateUtil.valid(json, "userName", 100, true);
        ValidateUtil.valid(json, "warehouseId", 10, true);
        ValidateUtil.valid(json, "effectiveDate", 0, false);
        ValidateUtil.valid(json, "expiredDate", 0, false);
        ValidateUtil.valid(json, "adUserId", 10, true);

        String userName = json.getString("userName");
        String fromBpartnerName = json.getString("fromBpartnerName");
        // 检查代销商账号
        checkUser(userName, fromBpartnerName);

        // 校验共享方是不是和当前卖家同一个商家
        if (validateSeller(userName, json.getLongValue("fromBpartnerId"))) {
            throw new ApiException(ErrorCode.CURRENT_USER_IS_SHARE_SELLER, "fromBpartnerId");
        }

        // 校验是否超过代销限额
        String fromBpartnerId = json.getString("fromBpartnerId");
        boolean isPass = checkPassSaleLimit(fromBpartnerId);
        if (isPass) {
            throw new ApiException(ErrorCode.CURRENT_SHARE_PASS_SALELIMIT, "fromBpartnerId");
        }

        CreateShareOrderSellCommand command = new CreateShareOrderSellCommand();
        command.setFormBpartnerId(json.getLongValue("fromBpartnerId"));// 共享方ID
        command.setUserName(json.getString("userName"));// 代销商账号
        command.setEffectiveDate(json.getDate("effectiveDate"));
        command.setExpiredDate(json.getDate("expiredDate"));
        command.setWarehouseId(json.getLongValue("warehouseId"));
        command.setAdUserId(json.getLongValue("adUserId"));
        command.setStatus(status);

        // 调用接口创建共享单
        ShareOrderSell order = shareOrderSellService.createShareOrder(command);
        return order;
    }

    /**
     * 检查代销商账号是否合法
     * 
     * @param userName 代销商账号
     * @param fromBpartnerName 共享方账号
     */
    private void checkUser(String userName, String fromBpartnerName) {
        // 查询ERP用户
        UserCommand userCommand = new UserCommand();
        userCommand.setLoginName(userName);
        User user = userService.getUser(userCommand);
        // ERP不存在，则去UMS检查
        if (user == null) {
            // 查询UMS用户
            CustomerQueryCommand cusCommand = new CustomerQueryCommand();
            cusCommand.setEmail(userName);
            CustomerInfoVO customer = umsCustomerService.queryUser(cusCommand);
            // 判断代销方是否激活代销服务
            if (customer == null) {
                // 用户不存在
                throw new ApiException(ErrorCode.CURRENT_USER_IS_NOT_EXIST, "userName");
            } else {
                if ("N".equals(customer.getIsActive())) {
                    // 代销商的代销服务未激活，需要发送邮件给客服，让客服处理
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("fromBpartner", fromBpartnerName);// 共享方账号
                    map.put("toBpartner", userName);// 代销商账号
                    // 发送邮件给客服处理
                    sendEmail(csEmail, "PerActive.ftl", map);
                    throw new ApiException(ErrorCode.CURRENT_USER_IS_NOT_ACTIVE, "userName");
                }
            }
        }
    }

    /**
     * 校验是否超过代销限额
     * 
     * @param fromBpartnerId 共享方
     */
    private boolean checkPassSaleLimit(String fromBpartnerId) {
        // 一个共享方存在的全部共享单(包含全部状态)
        List<ShareOrder> listShareOrder = shareOrderService.getUNVOShareOrder(Long.valueOf(fromBpartnerId));
        int counts = listShareOrder != null ? listShareOrder.size() : 0;

        BpartnerCommand bpartnerCommand = new BpartnerCommand();
        bpartnerCommand.setcBpartnerId(Long.valueOf(fromBpartnerId));
        Bpartner bpartner = bpartnerService.queryBpartnerById(bpartnerCommand);
        // 如果总共享单数 = 代销限额,则不允许再新增共享单(如果代销限额为空,则不限制)
        if (bpartner != null && bpartner.getSaleLimit() != null) {
            int limit = Integer.parseInt(bpartner.getSaleLimit());
            logger.info("【" + bpartner.getName() + "】 代销限额 ：" + limit);
            if (counts >= limit) {
                return true;
            }
        }
        return false;
    }

    /**
     * 校验当前下代销单用户和共享方是否属于同一商家
     * 
     * @param user
     * @param fromBparnerId
     * @return boolean
     */
    private boolean validateSeller(String userName, Long fromBparnerId) {
        UserCommand userCommand = new UserCommand();
        userCommand.setLoginName(userName);
        User user = userService.getUser(userCommand);
        if (user != null && (user.getBpartnerId().longValue() == fromBparnerId.longValue())) {
            return true;
        }
        return false;
    }

    /**
     * 发送邮件方法
     * 
     * @param to 目标对象
     * @param ftl 模板
     * @param model 参数
     */
    private void sendEmail(String to, String ftl, Map<String, Object> model) {
        String content = freemarkerMailContentService.processTemplateIntoString(ftl, model);
        String subject = freemarkerMailContentService.processSubjectFromContent(content, "万邑通邮件");
        SendEmailCommand command = new SendEmailCommand();
        command.setBody(content);
        command.setTo(to);
        command.setSubject(subject);
        emailService.send(command);
    }
}
